// list.h - Linked list.
//
// THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
// LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
// CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
//
// Copyright (c) 2016 dybai.
//

#include <pthread.h>

struct node {
  struct node *prev;
  struct node *next;
  pthread_mutex_t mtx;
  pthread_cond_t cond;
  void *data;
};

#define LIST_NODE_INIT(name) { &(name), &(name), PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, NULL }

static inline void INIT_LIST_NODE (struct node *pnode)
{
  pnode->prev = pnode;
  pnode->next = pnode;
  pthread_mutex_init(&pnode->mtx, NULL);
  pthread_cond_init(&pnode->cond, NULL);
  pthread_mutex_lock(&pnode->mtx);
  pnode->data = NULL;
  pthread_mutex_unlock(&pnode->mtx);
}

static inline void DESTROY_LIST_NODE (struct node *pnode)
{
  pthread_cond_destroy(&pnode->cond);
  pthread_mutex_destroy(&pnode->mtx);
}

static inline void node_add (struct node *pnew, struct node *phead)
{
  pnew->prev = phead;
  pnew->next = phead->next;
  pnew->next->prev = pnew;
  phead->next = pnew;
}

static inline void node_add_tail (struct node *pnew, struct node *phead)
{
  pnew->prev = phead->prev;
  pnew->next = phead;
  pnew->prev->next = pnew;
  phead->prev = pnew;
}

static inline void node_del (struct node *pnode)
{
  pnode->prev->next = pnode->next;
  pnode->next->prev = pnode->prev;
  pnode->prev = pnode->next = pnode;
}

#define __node_for_each(pnode, phead, member) \
  for (pnode = (phead)->member; pnode != (phead); pnode = pnode->member)

#define node_for_each(pnode, phead)  __node_for_each(pnode, phead, next)

#define node_for_each_prev(pnode, phead)  __node_for_each(pnode, phead, prev)

